<?php
	/**
	 * Application level Controller
	 *
	 * This file is application-wide controller file. You can put all
	 * application-wide controller-related methods here.
	 *
	 * PHP versions 4 and 5
	 *
	 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
	 * Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
	 *
	 * Licensed under The MIT License
	 * Redistributions of files must retain the above copyright notice.
	 *
	 * @copyright     Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
	 * @link          http://cakephp.org CakePHP(tm) Project
	 * @package       cake
	 * @subpackage    cake.app
	 * @since         CakePHP(tm) v 0.2.9
	 * @license       MIT License (http://www.opensource.org/licenses/mit-license.php)
	 */

	/**
	 * Application Controller
	 *
	 * Add your application-wide methods in the class below, your controllers
	 * will inherit them.
	 *
	 * @package       cake
	 * @subpackage    cake.app
	 */
	class AppController extends Controller {
		var $components = array('Acl',
			'Auth',
			'Session');

		function beforeFilter() {
			/** cambiar el login por defecto **/
			$this -> Auth -> authorize = 'actions';
			$this -> Auth -> loginAction = array('controller' => 'usuarios',
				'action' => 'login');
			$this -> Auth -> loginRedirect = array('controller' => 'usuarios',
				'action' => 'index');
			$this -> Auth -> logoutRedirect = array('controller' => 'usuarios',
				'action' => 'login');
			$this -> Auth -> userModel = 'Usuario';
			$this -> Auth -> actionPath = 'controllers/';

			/** Autorizaciones **/
			//$this -> Auth -> allow('registrar');
			//$this -> Auth -> allow('display');
			$this -> Auth -> allow('*');

			// Ahora, nos aseguramos de cerrar la sesión en caso que se deniegue el acceso vía Auth+Acl.
			// if($this -> action != 'login' && $this -> action != 'logout') {
			// $permisoActual = $this -> Acl -> check($this -> Auth -> user(), $this -> name . '/' . $this -> action);
			// if($permisoActual != true)
			// $this -> redirect($this -> Auth -> logout());
			// }

		}

		/**
		 *	initAro()
		 * Inicializa los grupos y los usuarios en la tabla ARO
		 */
		function initAro() {
			$aro = new Aro();

			# Aquí tenemos la información de nuestros grupos en un array sobre el cual iteraremos luego
			# foreign_key 1: Administradores
			$grupos = array(0 => array('parent_id' => null,
				'model' => 'Grupo',
				'foreign_key' => 1, ),
			# foreign_key 2: Supervisores
				1 => array('parent_id' => null,
					'model' => 'Grupo',
					'foreign_key' => 2, ),
			# foreign_key 3: Profesores
				2 => array('parent_id' => null,
					'model' => 'Grupo',
					'foreign_key' => 3, ),
			# foreign_key 4: Alumnos
				3 => array('parent_id' => null,
					'model' => 'Grupo',
					'foreign_key' => 4, ), );

			# Iterar para crear los ARO de los grupos
			foreach($grupos as $data) {
				# Recuerda llamar a create() cuando estés guardando información dentro de bucles...
				$aro -> create();
				# Guardar datos
				$aro -> save($data);
			}

			# foreign_key 1: administrador
			$usuarios = array(0 => array('parent_id' => 1,
				'model' => 'Usuario',
				'foreign_key' => 1, ),
			# foreign_key 2: supervisor
				1 => array('parent_id' => 2,
					'model' => 'Usuario',
					'foreign_key' => 2, ),
			# foreign_key 3: profesor
				2 => array('parent_id' => 3,
					'model' => 'Usuario',
					'foreign_key' => 3, ),
			# foreign_key 4: alumno
				3 => array('parent_id' => 4,
					'model' => 'Usuario',
					'foreign_key' => 4, ), );

			# Iterar y crear los AROs (como hijos)
			foreach($usuarios as $data) {
				# Recuerda llamar a create() cuando estés guardando información dentro de bucles...
				$aro -> create();
				# Guardar datos
				$aro -> save($data);
			}
		}

		/**
		 * buildAcl()
		 * Reconstruye el Acl basado en los controladores actuales de la aplicación.
		 *
		 * @return void
		 */
		function buildAcl() {
			$log = array();

			$aco = &$this -> Acl -> Aco;
			$root = $aco -> node('controllers');
			if(!$root) {
				$aco -> create(array('parent_id' => null,
					'model' => null,
					'alias' => 'controllers'));
				$root = $aco -> save();
				$root['Aco']['id'] = $aco -> id;
				$log[] = 'Creado el nodo Aco para los controladores';
			} else {
				$root = $root[0];
			}

			App::import('Core', 'File');
			$Controllers = Configure::listObjects('controller');
			$appIndex = array_search('App', $Controllers);
			if($appIndex !== false) {
				unset($Controllers[$appIndex]);
			}
			$baseMethods = get_class_methods('Controller');
			$baseMethods[] = 'initAro';
			$baseMethods[] = 'buildAcl';
			$baseMethods[] = 'initDB';

			# miramos en cada controlador en app/controllers
			foreach($Controllers as $ctrlName) {
				App::import('Controller', $ctrlName);
				$ctrlclass = $ctrlName . 'Controller';
				$methods = get_class_methods($ctrlclass);

				# buscar/crear nodo de controlador
				$controllerNode = $aco -> node('controllers/' . $ctrlName);
				if(!$controllerNode) {
					$aco -> create(array('parent_id' => $root['Aco']['id'],
						'model' => null,
						'alias' => $ctrlName));
					$controllerNode = $aco -> save();
					$controllerNode['Aco']['id'] = $aco -> id;
					$log[] = 'Creado el nodo Aco del controlador ' . $ctrlName;
				} else {
					$controllerNode = $controllerNode[0];
				}

				# Limpieza de los metodos, para eliminar aquellos en el controlador
				# y en las acciones privadas
				foreach($methods as $k => $method) {
					if(strpos($method, '_', 0) === 0) {
						unset($methods[$k]);
						continue ;
					}
					if(in_array($method, $baseMethods)) {
						unset($methods[$k]);
						continue ;
					}
					$methodNode = $aco -> node('controllers/' . $ctrlName . '/' . $method);
					if(!$methodNode) {
						$aco -> create(array('parent_id' => $controllerNode['Aco']['id'],
							'model' => null,
							'alias' => $method));
						$methodNode = $aco -> save();
						$log[] = 'Creado el nodo Aco para ' . $method;
					}
				}
			}
			debug($log);
		}

		function initDB() {
			// debe ejecutarse desde el controller usuarios, es decir http://dir/app/cake/usuarios/initDB
			// tira un error de vista pero no importa.

			$grupo = &$this -> Usuario -> Grupo;

			/** Administradores -- Grupo.id = 2  **/
			//Permite a los administradores hacer todo
			$grupo -> id = 1;
			$this -> Acl -> allow($grupo, 'controllers');
			// controllers es el nodo de nivel superior (root)

			/** Supervisores -- Grupo.id = 2 **/
			// permite a los editores postear y accesar los widgets
			$grupo -> id = 2;
			// deniega todo
			$this -> Acl -> deny($grupo, 'controllers');
			// permite Usuarios full
			$this -> Acl -> allow($grupo, 'controllers/Usuarios');
			// permite Alumnos full
			$this -> Acl -> allow($grupo, 'controllers/Alumnos');
			// permite Cursos full
			$this -> Acl -> allow($grupo, 'controllers/Cursos');

			/**
			 * Profesores -- Grupo.id = 3
			 **/
			$grupo -> id = 3;
			# deniega todo
			$this -> Acl -> deny($grupo, 'controllers');
			# permite Usuarios index para ser redirigido
			$this -> Acl -> allow($grupo, 'controllers/Usuarios/index');
			# permite Profesores index
			$this -> Acl -> allow($grupo, 'controllers/Profesores/index');
			# permite Cursos full
			//$this -> Acl -> allow($grupo, 'controllers/Cursos');

			/**
			 * Alumnos -- Grupo.id = 4
			 * */
			//permite a los usuarios añadir y editar posts y widgets
			$grupo -> id = 4;
			$this -> Acl -> deny($grupo, 'controllers');
			// deniega todo
			$this -> Acl -> allow($grupo, 'controllers/Alumnos/index');
			// permite ver su perfil de Alumno
			$this -> Acl -> allow($grupo, 'controllers/Alumnos/view');
			// permite ver su perfil de Alumno
			$this -> Acl -> allow($grupo, 'controllers/Alumnos/edit');
			// permite editar su perfil de Alumno
			$this -> Acl -> allow($grupo, 'controllers/Usuarios/index');
			// permite ver su perfil de Usuario
			//$this -> Acl -> allow($grupo, 'controllers/Usuarios/view');
			// permite ver su perfil de Usuario
			//$this -> Acl -> allow($grupo, 'controllers/Usuarios/edit');
			// permite editar su perfil de Usuario
		}

	}
